package com.exam.system.controller;

import com.exam.system.config.jwt.JwtTokenProvider;
import com.exam.system.config.security.SecurityUserDetails;
import com.exam.system.util.BodyUtil;
import jakarta.servlet.http.HttpServletRequest;
import lombok.extern.slf4j.Slf4j;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.http.ResponseEntity;
import org.springframework.security.authentication.AuthenticationManager;
import org.springframework.security.authentication.BadCredentialsException;
import org.springframework.security.authentication.UsernamePasswordAuthenticationToken;
import org.springframework.security.core.Authentication;
import org.springframework.security.core.annotation.AuthenticationPrincipal;
import org.springframework.security.core.context.SecurityContext;
import org.springframework.security.core.context.SecurityContextHolder;
import org.springframework.security.core.userdetails.UserDetails;
import org.springframework.web.bind.annotation.*;

import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

import static org.springframework.http.ResponseEntity.ok;

/**
 * @Author LY
 * @create 2023/9/25 17:42
 * @Description 登录
 */
@RestController
@RequestMapping("/auth")
@Slf4j
public class AuthController {

    @Autowired
    private AuthenticationManager authenticationManager;
    @Autowired
    private JwtTokenProvider jwtTokenProvider;

    private DateTimeFormatter dateTimeFormatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");

    /**
     * 打印当前用户信息
     * @return
     */
    @GetMapping("/getStr")
    public String getStr(){
        SecurityContext context = SecurityContextHolder.getContext();
        log.info("用户名：{}",context.getAuthentication().getName());
        log.info("用户权限：{}",context.getAuthentication().getAuthorities());
        log.info("用户是否登录：{}",context.getAuthentication().isAuthenticated());
        log.info("用户证书：{}",context.getAuthentication().getCredentials());
        log.info("用户地址ip：{}",context.getAuthentication().getDetails());
        log.info("用户信息：{}",context.getAuthentication().getPrincipal());
        return "getStr：" + context;
    }

    /**
     * 使用账号密码登录并使用JWT生成验证token
     * @param username
     * @param password
     * @return
     */
    @PostMapping("/authenticate")
    public ResponseEntity login(@RequestParam("username") String username,
                                @RequestParam("password") String password) {
        log.info("security登录 ===>>>{}_{}",username,password);
        try {
            // 生成一个包含账号密码的认证信息
            Authentication tokenInfo = new UsernamePasswordAuthenticationToken(username, password);
            // AuthenticationManager校验这个认证信息，返回一个已认证的Authentication
            Authentication authentication = authenticationManager.authenticate(tokenInfo);
            // 将返回的Authentication存到上下文中
            SecurityUserDetails securityUserDetails = (SecurityUserDetails) authentication.getPrincipal();
            String token = jwtTokenProvider.createToken(securityUserDetails);
            Map<String, Object> model = new HashMap<>();
            model.put("user_name", username);
            model.put("token", token);
            model.put("token_expiration", dateTimeFormatter.format(
                    jwtTokenProvider.getTokenExpiration(token)
                            .toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()));
            return ok(BodyUtil.build().ok("登录成功", model));
        }catch (BadCredentialsException e){
            return ok(BodyUtil.build().fail("账号或密码错误！"));
        }
    }

    /**
     * 刷新token
     * @param request
     * @return
     */
    @PostMapping(value = "/refresh_token")
    public ResponseEntity refreshToken(HttpServletRequest request) {
        log.info("刷新token ===>>>");
        String currToken = jwtTokenProvider.resolveToken(request);
        String newToken = jwtTokenProvider.refreshToken(currToken);
        Map<String, Object> model = new HashMap<>();
        model.put("username", jwtTokenProvider.getUsername(newToken));
        model.put("token", newToken);
        model.put("token_expiration", dateTimeFormatter.format(
                jwtTokenProvider.getTokenExpiration(newToken)
                        .toInstant().atZone(ZoneId.systemDefault()).toLocalDateTime()));
        return ok(BodyUtil.build().ok("刷新token成功", model));
    }

    /**
     * 检测当前登录用户信息
     * @param userDetails
     * @return
     */
    @GetMapping("/current_user")
    public ResponseEntity currentUser(@AuthenticationPrincipal UserDetails userDetails) {
        return ok(BodyUtil.build().ok("成功获取当前用户信息", userDetails));
    }
}
